package com.iot.web.vo;

import com.iot.common.utils.StringUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Cao.ning
 * @date 2022/5/11
 */
public class ElTree {

    public static void main(String[] args) {
        int a = 2;
        System.out.println(a >> 1);
        System.out.println(a >>> 1);
        System.out.println(a << 1);
        if((a = 3) < 0){
            System.out.println(123);
        }else{
            System.out.println(456);
            System.out.println(a);
        }
    }

    public static ElTree newRootInstance() {
        return new ElTree("0", "-999", "root", null);
    }
    public ElTree(){}
    public ElTree(String id, String pid, String label, String value) {
        this.id = id;
        this.pid = pid;
        this.label = label;
        this.value = value;
    }
    public ElTree(Object o, String idFieldName, String pidFieldName, String labelFieldName, String valueFieldName){
        try {
            Field idField = o.getClass().getDeclaredField(idFieldName);
            Field pidField = o.getClass().getDeclaredField(pidFieldName);
            Field labelField = o.getClass().getDeclaredField(labelFieldName);
            idField.setAccessible(true);
            pidField.setAccessible(true);
            labelField.setAccessible(true);
            String id = idField.get(o) == null ? "-1" : idField.get(o).toString();
            String pid = pidField.get(o) == null ? "0" : pidField.get(o).toString();
            String label = labelField.get(o) == null ? "-" : labelField.get(o).toString();
            this.id = id;
            this.pid = pid;
            this.label = label;
            if(StringUtils.isNotEmpty(valueFieldName)){
                Field valueField = o.getClass().getDeclaredField(valueFieldName);
                valueField.setAccessible(true);
                String value = valueField.get(o) == null ? "-" : valueField.get(o).toString();
                this.value = value;
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    public ElTree(Object o, String idFieldName, String pidFieldName, String labelFieldName, String valueFieldName, Set<Long> disableKeys){
        try {
            Field idField = o.getClass().getDeclaredField(idFieldName);
            Field pidField = o.getClass().getDeclaredField(pidFieldName);
            Field labelField = o.getClass().getDeclaredField(labelFieldName);
            idField.setAccessible(true);
            pidField.setAccessible(true);
            labelField.setAccessible(true);
            String id = idField.get(o) == null ? "-1" : idField.get(o).toString();
            String pid = pidField.get(o) == null ? "0" : pidField.get(o).toString();
            String label = labelField.get(o) == null ? "-" : labelField.get(o).toString();
            this.id = id;
            this.pid = pid;
            this.label = label;
            this.disabled = disableKeys != null && disableKeys.contains(id);
            if(StringUtils.isNotEmpty(valueFieldName)){
                Field valueField = o.getClass().getDeclaredField(valueFieldName);
                valueField.setAccessible(true);
                String value = valueField.get(o) == null ? "-" : valueField.get(o).toString();
                this.value = value;
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    public static <T> List<ElTree> genTreeList(List<T> list, String idFieldName, String pidFieldName, String labelFieldName){
        return genTreeList(list, idFieldName, pidFieldName, labelFieldName, null, null);
    }
    public static <T> List<ElTree> genTreeList(List<T> list, String idFieldName, String pidFieldName, String labelFieldName, String valueFieldName){
        return genTreeList(list, idFieldName, pidFieldName, labelFieldName, valueFieldName, null);
    }
    public static <T> List<ElTree> genTreeList(List<T> list, String idFieldName, String pidFieldName, String labelFieldName, Set<Long> disableKeys){
        return genTreeList(list, idFieldName, pidFieldName, labelFieldName, null, disableKeys);
    }
    public static <T> List<ElTree> genTreeList(List<T> list, String idFieldName, String pidFieldName, String labelFieldName, String valueFieldName, Set<Long> disableKeys){
        ElTree elTree = ElTree.newRootInstance();
        List<ElTree> elTreeList = list.stream().map(item -> new ElTree(item, idFieldName, pidFieldName, labelFieldName, valueFieldName, disableKeys)).collect(Collectors.toList());
        ElTree.buildTree(elTree, elTreeList);
        return elTree.getChildren();
    }
    private static void buildTree(ElTree elTree, List<ElTree> elTreeList) {
        Map<String, List<ElTree>> elTreeMap = elTreeList.stream().collect(Collectors.groupingBy(ElTree::getPid));
        elTree.setChildren(elTreeMap.get(elTree.getId()));
        elTreeList.removeAll(elTree.getChildren());
        for(ElTree elTreeChild : elTree.getChildren()){
            buildTree(elTreeChild, elTreeList);
        }
    }

    private String id;
    private String pid;
    private String label;
    private String value;
    private boolean disabled;
    private List<ElTree> children;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPid() {
        return pid;
    }

    public void setPid(String pid) {
        this.pid = pid;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public boolean isDisabled() {
        return disabled;
    }

    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }

    public List<ElTree> getChildren() {
        return children;
    }

    public void setChildren(List<ElTree> children) {
        this.children = children == null ? new ArrayList<ElTree>() : children;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ElTree elTree = (ElTree) o;
        return id.equals(elTree.id);
    }
}
